/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package app.model_package;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;

/**
 *
 * @author haythem
 */
public class LogModel {

    // the ID that allows to identify
    // the Log
    private String logID ;

    // list of the cases included in the
    // Log
    private ArrayList<CaseModel> listCases;

    // list of the cases IS in the Log
    private ArrayList<String> listCasesID ;

    // Event ID generator
    private Integer eventIDGen = 0 ;


    //////////// constructors //////////////////////


    /**
     *
     * @param logID
     * @param listCases
     */
    public LogModel(String logID, ArrayList<CaseModel> listCases) {
        this.logID = logID;
        this.listCases = listCases;
    }

    /**
     * the constructor that must be used
     * @param logID
     */
    public LogModel(String logID) {
        this.logID = logID;
        this.listCases = new ArrayList<CaseModel>();
        this.listCasesID = new ArrayList<String>();
    }



    /////////// getters and setters /////////////////

    /**
     *
     * @return
     */
    public ArrayList<String> getListCasesID() {
        return listCasesID;
    }

    /**
     *
     * @param listCasesID
     */
    public void setListCasesID(ArrayList<String> listCasesID) {
        this.listCasesID = listCasesID;
    }

    /**
     *
     * @param caseID
     */
    public void addCasesID(String caseID) {
        this.listCasesID.add(caseID);
    }

    /**
     *
     * @param caseID
     */
    public void deleteCasesID(String caseID) {
        this.listCasesID.remove((String)caseID);
    }


    /**
     *
     * @return
     */
    public ArrayList<CaseModel> getListCases() {
        return listCases;
    }

    /**
     *
     * @return
     */
    public String getLogID() {
        return logID;
    }

    

    /**
     *
     * @param logID
     */
    public void setLogID(String logID) {
        this.logID = logID;
    }

    public void debug_info(){
    	System.out.println("Log ID: "+ this.logID);
    	for (int i=0;i<this.listCases.size();i++){
    		System.out.println("Log ID: "+ listCases.get(i).getCaseID());
    		System.out.println("Event list size: " + listCases.get(i).getEventsList().size());
    		for (int j=0;j<listCases.get(i).getEventsList().size();j++){
    			System.out.println("** Event("+j+") info: "+listCases.get(i).getEventsList().get(j).getTask());
    		}
    	}
    }
    
    ////////////////////////////
    /**
     *
     * @param fileName
     */
    public void toString(String fileName){
        String s= "<?xml version=\"1.0/\" encoding=\"GBK\" ?> \n" ;
        s=s+"<root>\n";
        for(int i=0;i<listCases.size();i++){
            CaseModel c = listCases.get(i);
             s = s+ c.toString();
        }
        s=s+"</root>\n";

        // file creation !!!!! here
        //String adressedufichier = System.getProperty("user.dir") + "/"+ fileName;
        //System.out.println(adressedufichier);
			//on met try si jamais il y a une exception
			try
			{
				/**
				 * BufferedWriter a besoin d un FileWriter,
				 * les 2 vont ensemble, on donne comme argument le nom du fichier
				 * true signifie qu on ajoute dans le fichier (append), on ne marque pas par dessus

				 */
				FileWriter fw = new FileWriter(fileName, false);

				// le BufferedWriter output auquel on donne comme argument le FileWriter fw cree juste au dessus
				BufferedWriter output = new BufferedWriter(fw);

				//on marque dans le fichier ou plutot dans le BufferedWriter qui sert comme un tampon(stream)
				output.write(s);
				//on peut utiliser plusieurs fois methode write

				output.flush();
				//ensuite flush envoie dans le fichier, ne pas oublier cette methode pour le BufferedWriter

				output.close();
				//et on le ferme
				System.out.println("fichier créé");
			}
			catch(IOException ioe){
				System.out.print("Erreur : ");
				ioe.printStackTrace();
				}

    }
//////////////////////////////////////////////
//////////////////   cases //////////////////
/////////////////////////////////////////////

    // probably wont be used 
    /**
     *
     * @param listCases
     */
    public void setListCases(ArrayList<CaseModel> listCases) {
        this.listCases = listCases;
    }

    /**
     *
     * @param case_
     */
    public void addCase(CaseModel case_) {
        // we add caseID to the list if it doesn't
        // already exist
        String s= case_.getCaseID();
        boolean b = false ;
        int i = 0;
        while ((i<listCases.size()) && (b == false)){
            b = this.listCasesID.get(i).equals((String) s);
            if (b==false) {i++;}
        }
        // if the ID doesn't exist already in
        // the list (b still equals to false
        // then we add the new ID
        if (b==false){
            this.listCasesID.add(s);
             // add the case
             this.listCases.add(case_);
        }

       // ????????? problem oof fusion if the case already exists  what to do ??
    }

    /**
     *
     * @param case_
     */
    public void deleteCase(CaseModel case_) {
        // delete the case
        this.listCases.remove((CaseModel) case_);
        // delete de caseID from the list
        this.listCasesID.remove((String) (case_.getCaseID()));
    }

    /**
     * this method allows to change the ID
     * of a given case precised by its ID
     * @param previousCaseID : the Case ID to change
     * @param newCaseID : the new Case ID
     */
    public void editCaseID(String previousCaseID, String newCaseID){
//        boolean b = false;
//        int i = 0 ;
//        // for cases list
//        while ((i<listCases.size()) && (b == false)){
//            // we look for the case with the ID
//            // previousCaseID
//            b = this.listCases.get(i).getCaseID().equals((String)previousCaseID);
//            if (b==false) {i++;}
//            else {
//                this.listCases.get(i).setCaseID(newCaseID);
//            }
//        }
        int i = lookForCase(previousCaseID);
        if ((i>=0) && (i<listCases.size())){
            int k = lookForCase(newCaseID);
            if((k>=0) && (k<listCases.size())){
                /// fusion
                if (i!=k){
                    fusion(i,k);
                }
            }
            else{
                this.listCases.get(i).setCaseID(newCaseID);
            }
        }
        else {
            System.out.println(" this case doesn't exist : "+previousCaseID);
        }
        // for the cases IDs list
        boolean b1 = false;
        int j = 0 ;
        while ((j<listCasesID.size()) && (b1 == false)){
            // we look for the case with the ID
            // previousCaseID
            b1 = this.listCasesID.get(j).equals((String)previousCaseID);
            if (b1==false) {j++;}
            else {
                this.listCasesID.remove((String) previousCaseID);
                this.listCasesID.add(newCaseID);
            }
        }

//        listCasesID.remove((String) previousCaseID);
//        listCasesID.add(newCaseID);
//        Case c = this.listCases.get((String) previousCaseID);
//        // c!= null <=> we find a correspondance
//        if (c != null){
//            this.listCases.remove((String) previousCaseID);
//            c.setCaseID(newCaseID);
//            this.listCases.put(newCaseID, c);
//        }
//        // else this case doesn't exist
//        else{
//            System.out.println(previousCaseID+" case doesn't exist");
//        }
    }

    /**
     * this method returns the index of the
     * case with the ID caseID if it exists
     * in listCases else returns -1
     * @param caseID : the case's ID we look for
     * @return : the case index in the list of cases
     */
    public int lookForCase(String caseID){
        boolean b = false;
        int i = 0 ;
        // for cases list
        while ((i<listCases.size()) && (b == false)){
            // we look for the case with the ID
            // previousCaseID
            b = this.listCases.get(i).getCaseID().equals((String)caseID);
            if (b==false) {i++;}
        }
        if (b==true){
            return i;
        }
        else {return -1;}
    }


    /**
     * this method allow to add the events of the case associated
     * to the addedCaseIndex element in listCases to the case associated
     * to the receivingCaseIndex element in listCases before deleting
     * the first one from the list
     * @param addedCaseIndex
     * @param receivingCaseIndex
     */
    public void fusion(int addedCaseIndex,int receivingCaseIndex){
        CaseModel c = listCases.get(addedCaseIndex);
        listCases.get(receivingCaseIndex).addCase(c);
        listCases.remove(addedCaseIndex);
    }
//////////////////////////////////////////////
//////////////////   event //////////////////
/////////////////////////////////////////////

    /**
     * in this method we suppose that the level before
     * gives the listReceivers and the date
     * @param caseID
     * @param taskID
     * @param initiator
     * @param listReceivers
     * @param perfomative
     * @param date
     */
    public void addEvent(String caseID, String taskID,String initiator, ArrayList<String> listReceivers,String perfomative, String conversation, Date date){
        EventModel e = new EventModel(eventIDGen.toString(), taskID, initiator, listReceivers, perfomative,conversation, date);
        eventIDGen++;
        boolean b = false ;
        int i = 0;
        while ((i<listCases.size()) && (b == false)){
            b = this.listCases.get(i).getCaseID().equals((String) caseID);
            if (b==false) {i++;}
            else {
                this.listCases.get(i).addEvent(e);
            }
        }
        // if the case ID doesn't exist already in
        // the list (b still equals to false
        // then we add the new ID
        if (b==false){
            CaseModel c = new CaseModel(caseID);
            c.addEvent(e);
            this.addCase(c);
        }
    }


    /**
     *
     * @param caseID
     * @param eventID
     * @param taskID
     * @param initiator
     * @param listReceivers
     * @param perfomative
     * @param date
     */
    public void editEvent(String caseID,String eventID, String taskID,String initiator, ArrayList<String> listReceivers,String perfomative, Date date){
        boolean b = false ;
        int i = 0;
        while ((i<listCases.size()) && (b == false)){
            b = this.listCases.get(i).getCaseID().equals((String) caseID);
            if (b==false) {i++;}
            else {
                this.listCases.get(i).editEvent(eventID,taskID,initiator,listReceivers,perfomative,date);
            }
        }
        if (b==false){
            System.out.println(" the case doesn't exist  "+caseID);
        }
    }



    /**
     * 
     * @param eventID
     * @param caseID
     */
    public void deleteEvent(String eventID, String caseID){
        int i = lookForCase(caseID);
        if ((i>=0) && (i<this.listCases.size())){
            this.listCases.get(i).deleteEvent(eventID);
        }
        else {
            System.out.println(caseID+" doesn't exist !!");
        }
    }


    /**
     * this method returns the events' list in the case
     * with ID caseID
     * @param caseID
     * @return
     */
    public ArrayList<EventModel> getListEvents(String caseID){
        int i = lookForCase(caseID);
        ArrayList<EventModel> listEvents = new ArrayList<EventModel>();
        if ((i>=0) && (i<this.listCases.size())){
            listEvents = this.listCases.get(i).getEventsList();
        }
        else {
            System.out.println(caseID+" doesn't exist !!");
        }
        return listEvents;
    }

//////////////////////////////////////////////
//////////////////   task //////////////////
/////////////////////////////////////////////

    /**
     *
     * @param previousTaskID
     * @param newtaskID
     * @param eventID
     * @param caseID
     */
    public void modifTask(String previousTaskID,String newtaskID , String eventID, String caseID){
        int i = lookForCase(caseID);
        if ((i>=0) && (i<this.listCases.size())){
            this.listCases.get(i).modifTask(eventID, previousTaskID, newtaskID);
        }
        else {
            System.out.println(caseID+" doesn't exist !!");
        }
    }
    
    /**
     * this method deletes all the events having 
     * the task "taskID" in the the case with the ID
     * ccaseID
     * @param taskID
     * @param caseID
     */
    public void deleteTaskInCase(String taskID , String caseID){
        int i = lookForCase(caseID);
        if ((i>=0) && (i<this.listCases.size())){
            this.listCases.get(i).deleteTaskInCase(taskID);
        }
        else {
            System.out.println(caseID+" doesn't exist !!");
        }
    }

    /**
     * this method deletes from the log all tasks
     * with ID taskID
     * @param taskID
     */
    public void deleteTask(String taskID){
        for(int i=0;i<listCases.size();i++){
            this.listCases.get(i).deleteTaskInCase(taskID);
        }
    }


    /**
     * edits a task ID in a given case
     * @param previousTaskID
     * @param newTaskID
     * @param caseID
     */
    public void editTaskInCase(String previousTaskID, String newTaskID , String caseID){
        int i = lookForCase(caseID);
        if ((i>=0) && (i<this.listCases.size())){
            this.listCases.get(i).editTaskInCase(previousTaskID,newTaskID);
        }
        else {
            System.out.println(caseID+" doesn't exist !!");
        }
    }




    /**
     * edits task ID in all the Log 
     * @param previousTaskID
     * @param newTaskID
     */
    public void editTask(String previousTaskID, String newTaskID){
        for (int i=0;i<listCases.size();i++){
            listCases.get(i).editTaskInCase(previousTaskID, newTaskID);
        }
    }



//////////////////////////////////////////////
//////////////////   Agent (initiator or receiver) //////////////////
/////////////////////////////////////////////


    /**
     * in all events of the given case this method looks if the some
     * of the agents operating have as ID previousAgentID and
     * replace it by newAgentID
     * @param previousAgentID
     * @param newAgentID
     * @param caseID
     */
    public void editAgentInCase(String previousAgentID, String newAgentID,String caseID){
        int i = lookForCase(caseID);
            if ((i>=0) && (i<this.listCases.size())){
                this.listCases.get(i).editAgentInCase(previousAgentID,newAgentID);
            }
            else {
                System.out.println(caseID+" doesn't exist !!");
            }
    }

    /**
     *
     * @param previousAgentID
     * @param newAgentID
     */
    public void editAgent(String previousAgentID, String newAgentID){
            for(int i=0;i<listCases.size();i++) {
                this.listCases.get(i).editAgentInCase(previousAgentID,newAgentID);
            }
    }


//////////////////////////////////////////////
//////////////////   initiator //////////////////
/////////////////////////////////////////////

    /**
     * 
     * @param previousIniatorID
     * @param newIniatorID
     * @param eventID
     * @param caseID
     */
    public void modifIniator(String previousIniatorID,String newIniatorID , String eventID, String caseID){
        int i = lookForCase(caseID);
        if ((i>=0) && (i<this.listCases.size())){
            this.listCases.get(i).modifIniator(eventID, previousIniatorID, newIniatorID);
        }
        else {
            System.out.println(caseID+" doesn't exist !!");
        }
    }

//////////////////////////////////////////////
//////////////////   receivers //////////////////
/////////////////////////////////////////////


    /**
     *
     * @param previousReceiverID
     * @param newReceiverID
     * @param eventID
     * @param caseID
     */
    public void modifReceiver(String previousReceiverID,String newReceiverID , String eventID, String caseID){
        int i = lookForCase(caseID);
        if ((i>=0) && (i<this.listCases.size())){
            this.listCases.get(i).modifReceiver(eventID, previousReceiverID, newReceiverID);
        }
        else {
            System.out.println(caseID+" doesn't exist !!");
        }
    }



    /**
     *
     * @param ReceiverID
     * @param eventID
     * @param caseID
     */
    public void deleteReceiver(String ReceiverID , String eventID, String caseID){
        int i = lookForCase(caseID);
        if ((i>=0) && (i<this.listCases.size())){
            this.listCases.get(i).deleteReceiver(eventID,ReceiverID);
        }
        else {
            System.out.println(caseID+" doesn't exist !!");
        }
    }



    /**
     *
     * @param ReceiverID
     * @param eventID
     * @param caseID
     */
    public void addReceiver(String ReceiverID , String eventID, String caseID){
        int i = lookForCase(caseID);
        if ((i>=0) && (i<this.listCases.size())){
            this.listCases.get(i).addReceiver(eventID,ReceiverID);
        }
        else {
            System.out.println(caseID+" doesn't exist !!");
        }
    }

//////////////////////////////////////////////
//////////////////   performative //////////////////
/////////////////////////////////////////////

    /**
     *
     * @param previousPerformativ
     * @param newPerformativ
     * @param eventID
     * @param caseID
     */
    public void modifPerformativ(String previousPerformativ,String newPerformativ , String eventID, String caseID){
        int i = lookForCase(caseID);
        if ((i>=0) && (i<this.listCases.size())){
            this.listCases.get(i).modifPerformativ(eventID, previousPerformativ, newPerformativ);
        }
        else {
            System.out.println(caseID+" doesn't exist !!");
        }
    }


    /**
     * it edits a performativ in all events of a given case
     * @param previousPerformativ
     * @param newPerformativ
     * @param caseID
     */
    public void editPerformativInCase(String previousPerformativ,String newPerformativ , String caseID){
        int i = lookForCase(caseID);
        if ((i>=0) && (i<this.listCases.size())){
            this.listCases.get(i).editPerformativInCase( previousPerformativ, newPerformativ);
        }
        else {
            System.out.println(caseID+" doesn't exist !!");
        }
    }


    /**
     * in all Log
     * @param previousPerformativ
     * @param newPerformativ
     */
    public void editPerformativ(String previousPerformativ,String newPerformativ){
        for (int i=0;i<listCases.size();i++){
            this.listCases.get(i).editPerformativInCase( previousPerformativ, newPerformativ);
        }
    }
//////////////////////////////////////////////
//////////////////   conversation //////////////////
/////////////////////////////////////////////



    /**
     * edit the conversation ID in a specified event of a specified case
     * @param previousConversation
     * @param newConversation
     * @param eventID
     * @param caseID
     */
    public void modifConversation(String previousConversation,String newConversation , String eventID, String caseID){
        int i = lookForCase(caseID);
        if ((i>=0) && (i<this.listCases.size())){
            this.listCases.get(i).modifConversation(eventID, previousConversation, newConversation);
        }
        else {
            System.out.println(caseID+" doesn't exist !!");
        }
    }


    /**
     * edit the conversation ID in all events of a specified case
     * @param previousConversation
     * @param newConversation
     * @param caseID
     */
    public void modifConversationInCase(String previousConversation,String newConversation , String caseID){
        int i = lookForCase(caseID);
        if ((i>=0) && (i<this.listCases.size())){
            this.listCases.get(i).modifConversationInCase(previousConversation, newConversation);
        }
        else {
            System.out.println(caseID+" doesn't exist !!");
        }
    }



    /**
     * does the edition in all the Log
     * @param previousConversation
     * @param newConversation
     */
     public void modifConversation(String previousConversation,String newConversation){
         for (int i=0;i<listCases.size();i++){
            this.listCases.get(i).modifConversationInCase(previousConversation, newConversation);
        }
    }




//////////////////////////////////////////////
//////////////////   date //////////////////
/////////////////////////////////////////////

    /**
     *
     * @param previousDate
     * @param newDate
     * @param eventID
     * @param caseID
     */
    public void modifDate(Date previousDate,Date newDate , String eventID, String caseID){
        int i = lookForCase(caseID);
        if ((i>=0) && (i<this.listCases.size())){
            this.listCases.get(i).modifDate(eventID, previousDate, newDate);
        }
        else {
            System.out.println(caseID+" doesn't exist !!");
        }
    }



    /**
     * edits the given date in all the events of the given case
     * @param previousDate
     * @param newDate
     * @param caseID
     */
    public void modifDateInCase(Date previousDate,Date newDate, String caseID){
        int i = lookForCase(caseID);
        if ((i>=0) && (i<this.listCases.size())){
            this.listCases.get(i).modifDateInCase(previousDate, newDate);
        }
        else {
            System.out.println(caseID+" doesn't exist !!");
        }
    }


    /**
     * edits all the previousDate in the Log 
     * @param previousDate
     * @param newDate
     */
     public void modifDate(Date previousDate,Date newDate){
       for (int i=0;i<listCases.size();i++){
            this.listCases.get(i).modifDateInCase(previousDate, newDate);
        }
    }


// this method is in the class Tree
//     public Tree buildTree(){
//                Tree arbre;
//		//Création d'une racine
//		DefaultMutableTreeNode racine = new DefaultMutableTreeNode(this.getLogID());
//                // loop for the cases
//                for (int i=0;i<listCases.size();i++){
//		//Nous allons ajouter des branches et des feuilles à notre racine
//			DefaultMutableTreeNode caseTree = new DefaultMutableTreeNode(listCases.get(i).getCaseID());
//                        //lopp for the events
//			for(int j = 0; j < listCases.get(i).getEventsList().size(); j++){
//					DefaultMutableTreeNode eventTree = new DefaultMutableTreeNode(listCases.get(i).getEventsList().get(j).getEventID());
//					//Cette fois, on ajoute nos feuilles
//					eventTree.add(new DefaultMutableTreeNode("Task : "+listCases.get(i).getEventsList().get(j).getTask()));
////                                        System.out.println("Task : "+listCases.get(i).getEventsList().get(j).getTask());
//                                        eventTree.add(new DefaultMutableTreeNode("Performative : "+listCases.get(i).getEventsList().get(j).getPerfomative()));
////                                        System.out.println("Performative : "+listCases.get(i).getEventsList().get(j).getPerfomative());
//                                        eventTree.add(new DefaultMutableTreeNode("Initiator : "+listCases.get(i).getEventsList().get(j).getIniator()));
////                                        System.out.println("Initiator : "+listCases.get(i).getEventsList().get(j).getIniator());
//                                        for(int k=0;k<listCases.get(i).getEventsList().get(j).getListReceivers().size();k++){
//                                             eventTree.add(new DefaultMutableTreeNode("Receiver n°"+k+" : "+listCases.get(i).getEventsList().get(j).getListReceivers().get(k)));
////                                             System.out.println("Receiver n°"+k+" : "+listCases.get(i).getEventsList().get(j).getListReceivers().get(k));
//                                        }
//                                        eventTree.add(new DefaultMutableTreeNode("Date : "+listCases.get(i).getEventsList().get(j).getDate().toString()));
////                                        System.out.println("Date : "+listCases.get(i).getEventsList().get(j).getDate().toString());
//					caseTree.add(eventTree);
//			}
//
//			//On ajoute la feuille ou la branche à la racine
//			racine.add(caseTree);
//
//                }
//		//On crée, avec notre hiérarchie, un arbre
//		arbre = new Tree(racine);
//
//
//		//Que nous plaçons sur le ContentPane de notre JFrame à l'aide d'un scroll
//		//this.getContentPane().add(new JScrollPane(arbre));
//                return arbre;
//	}
    

}
